﻿/* Copyright 2011 Michiel Fortuin
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * */


using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;

namespace sharplog
{
	/// <summary>
	/// A formater for readible text. It produces a byte[] as message output.
	/// </summary>
	public class TextFormater:Formater
	{
		/// <summary>
		/// The encoding used in the output
		/// </summary>
		public Encoding Encoding { get; set; }
		/// <summary>
		/// The application name
		/// </summary>
		public string AppName { get; set; }
		/// <summary>
		/// The process ID. If this is null or empty it will automaticaly get the PID from the system.
		/// </summary>
		public string ProcID { get; set; }

		/// <summary>
		/// Creates a Text formater. It uses the system default encoding. 
		/// </summary>
		/// <param name="appname">The application name. If this is null or empty. It autogenerates a name.</param>
		/// <param name="procId">The ID of the process. If it is null or emtpy then it wil get your PID.</param>
		public TextFormater(string appname = null, string procId = null)
		{
			if (string.IsNullOrWhiteSpace(appname))
			{
				Assembly asm = Assembly.GetEntryAssembly();
				if (asm == null)
				{
					this.AppName = "SharpLog";
				}
				else
				{
					this.AppName = asm.GetName().Name;
				}
			}
			else
			{
				this.AppName = appname;
			}
			string ProcID = string.IsNullOrWhiteSpace(procId) ? Process.GetCurrentProcess().Id.ToString() : procId;
			this.Encoding = System.Text.Encoding.Default;
		}

		/// <summary>
		/// Creates a Text formater
		/// </summary>
		/// <param name="encoding">The encoding used to output the data.</param>
		/// <param name="appname">The application name. If this is null or empty. It autogenerates a name.</param>
		/// <param name="procId">The ID of the process. If it is null or emtpy then it wil get your PID.</param>
		public TextFormater(Encoding encoding, string appname = null, string procId = null)
		{
			if (string.IsNullOrWhiteSpace(appname))
			{
				Assembly asm = Assembly.GetEntryAssembly();
				if (asm == null)
				{
					this.AppName = "SharpLog";
				}
				else
				{
					this.AppName = asm.GetName().Name;
				}
			}
			else
			{
				this.AppName = appname;
			}
			string ProcID = string.IsNullOrWhiteSpace(procId) ? Process.GetCurrentProcess().Id.ToString() : procId;
			this.Encoding = encoding;
		}

		#region Overrides of Formater

		/// <summary>
		/// Constructs a message for sending
		/// </summary>
		/// <param name="level">The level of the message.</param>
		/// <param name="facility">The facility from where the log message originates.</param>
		/// <param name="messageID">An Id given to the message.</param>
		/// <param name="message">The message itself.</param>
		/// <returns>An object for a specifice sender.</returns>
		internal override object ConstructMessage(Level level, Facility facility, string messageID, string message)
		{	
			DateTime date = DateTime.Now;
			string procId = string.IsNullOrWhiteSpace(this.ProcID) ? Process.GetCurrentProcess().Id.ToString() : this.ProcID;

			return this.Encoding.GetBytes(string.Format("{0} {1}[{2}] - {3}: {4}\n", date, AppName, procId, level, message));
		}
		#endregion
	}

	/// <summary>
	/// A sender that outputs too a stream. It expects a byte[] as message. This can be used with a file output or Console output.
	/// </summary>
	public class SenderStream: Sender
	{
		private Stream outputStream;

		/// <summary>
		/// creates a Sender that uses a output stream. For example a file or the console output stream.
		/// </summary>
		/// <param name="outputStream"></param>
		public SenderStream(Stream outputStream)
		{
			this.outputStream = outputStream;
		}

		~SenderStream()
		{
			this.outputStream.Close();
		}

		#region Overrides of Sender

		/// <summary>
		/// Sends a message.
		/// </summary>
		/// <param name="data">The pre-formated message from a specific formater.</param>
		internal override void SendMessage(object data)
		{
			byte[] d = (byte[]) data;
			outputStream.Write(d, 0, d.Length);
		}

		#endregion
	}
}
